/****************************************************************************
 * infineon/chips/tc3xx/tc3xx_allocateheap.c
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.  The
 * ASF licenses this file to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 * License for the specific language governing permissions and limitations
 * under the License.
 *
 ****************************************************************************/

#include <nuttx/config.h>
#include <sys/types.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/board.h>
#include <arch/board/board.h>

#include "tricore_internal.h"

/****************************************************************************
 * Name: up_allocate_heap
 *
 * Description:
 *   This function will be called to dynamically set aside the heap region.
 *
 *   For the kernel build (CONFIG_BUILD_KERNEL=y) with both kernel- and
 *   user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the
 *   size of the unprotected, user-space heap.
 *
 *   If a protected kernel-space heap is provided, the kernel heap must be
 *   allocated (and protected) by an analogous up_allocate_kheap().
 *
 ****************************************************************************/
#if defined(__TASKING__)
#define TC3XX_PSRAM0_BASE_ADDR  0x70100000
#define TC3XX_PSRAM1_BASE_ADDR  0x60100000
#define TC3XX_PSRAM2_BASE_ADDR  0x50100000
#define TC3XX_PSRAM3_BASE_ADDR  0x40100000
#define TC3XX_PSRAM4_BASE_ADDR  0x30100000
#define TC3XX_PSRAM5_BASE_ADDR  0x10100000
#define TC3XX_PSRAM_SIZE        0x10000

static const unsigned long per_cpu_psram_base_addr[] = {
	TC3XX_PSRAM0_BASE_ADDR,	TC3XX_PSRAM1_BASE_ADDR,
	TC3XX_PSRAM2_BASE_ADDR,	TC3XX_PSRAM3_BASE_ADDR,
	TC3XX_PSRAM4_BASE_ADDR,	TC3XX_PSRAM5_BASE_ADDR,
};
#elif defined(__GNUC__) && defined(__TRICORE__)
#define DECLARE_LINKER_SYMBOLS(cpu)                                            \
	extern unsigned int __HEAP##cpu##_START[];                             \
	extern unsigned int __HEAP##cpu##_END[]

DECLARE_LINKER_SYMBOLS(0);
DECLARE_LINKER_SYMBOLS(1);
DECLARE_LINKER_SYMBOLS(2);
DECLARE_LINKER_SYMBOLS(3);
DECLARE_LINKER_SYMBOLS(4);
DECLARE_LINKER_SYMBOLS(5);

#define __HEAP(cpu) __HEAP##cpu##_START
#define __HEAP_END(cpu) __HEAP##cpu##_END

extern unsigned int __HEAP[];
extern unsigned int __HEAP_END[];
#endif

void up_allocate_heap(void **heap_start, size_t *heap_size)
{
#if defined(__TASKING__)
	*heap_size = (size_t)TC3XX_PSRAM_SIZE;
	*heap_start = (void *)per_cpu_psram_base_addr[up_cpu_index()];
#elif defined(__GNUC__) && defined(__TRICORE__)
#if defined(CONFIG_BMP)
	unsigned int cpu_id = up_cpu_index();

	switch (cpu_id) {
	case 0:
		*heap_start = (void *)(__HEAP(0));
		*heap_size = (size_t)((unsigned long)__HEAP_END(0) - (unsigned long)__HEAP(0));
		break;
	case 1:
		*heap_start = (void *)(__HEAP(1));
		*heap_size = (size_t)((unsigned long)__HEAP_END(1) - (unsigned long)__HEAP(1));
		break;
	case 2:
		*heap_start = (void *)(__HEAP(2));
		*heap_size = (size_t)((unsigned long)__HEAP_END(2) - (unsigned long)__HEAP(2));
		break;
	case 3:
		*heap_start = (void *)(__HEAP(3));
		*heap_size = (size_t)((unsigned long)__HEAP_END(3) - (unsigned long)__HEAP(3));
		break;
	case 4:
		*heap_start = (void *)(__HEAP(4));
		*heap_size = (size_t)((unsigned long)__HEAP_END(4) - (unsigned long)__HEAP(4));
		break;
	case 5:
		*heap_start = (void *)(__HEAP(5));
		*heap_size = (size_t)((unsigned long)__HEAP_END(5) - (unsigned long)__HEAP(5));
		break;
	default:
		*heap_start = NULL;
		*heap_size = 0;
		break;
	}
#else
	*heap_start = __HEAP;
	*heap_size = (unsigned long)__HEAP_END - (unsigned long)(__HEAP);
#endif /* CONFIG_BMP */
#endif /* __TASKING__ */
}
